package bk

import (
	"errors"
	"fmt"
	"os"
	"sync"
)

type t_createfun func(args ...interface{}) (rval interface{}, err error)

type CreateFactory struct {
	lock      *sync.RWMutex
	beanMap   map[string]interface{}
	createMap map[string]t_createfun
}

// 接口, 对象都创建完后
type I_initializer interface {
	DoInitialize()
}

var (
	createFactory *CreateFactory
)

func newCreateFactory() *CreateFactory {
	rval := &CreateFactory{
		lock:      new(sync.RWMutex),
		beanMap:   make(map[string]interface{}),
		createMap: make(map[string]t_createfun),
	}
	return rval
}

func RegisterCreate(id string, cfun t_createfun) error {
	createFactory.lock.Lock()
	defer createFactory.lock.Unlock()
	if createFactory.createMap[id] != nil {
		fmt.Fprintf(os.Stderr, "%s is registed\n", id)
		return errors.New(id + " is registed!")
	}
	createFactory.createMap[id] = cfun
	return nil
}

func UnregisterCreate(id string) {
	createFactory.lock.Lock()
	defer createFactory.lock.Unlock()
	delete(createFactory.createMap, id)
	return
}

func CreateInstance(id string, args ...interface{}) (rval interface{}, err error) {
	createFactory.lock.RLock()
	defer createFactory.lock.RUnlock()
	f := createFactory.createMap[id]
	if f == nil {
		return nil, fmt.Errorf("[%s] is not registed!", id)
	}

	return f(args...)
}

func GetBean(id string) interface{} {
	createFactory.lock.RLock()
	defer createFactory.lock.RUnlock()
	return createFactory.beanMap[id]
}

func RegisterBean(id string, val interface{}) {
	createFactory.lock.Lock()
	defer createFactory.lock.Unlock()
	createFactory.beanMap[id] = val
}

func RemoveBean(id string) {
	createFactory.lock.Lock()
	defer createFactory.lock.Unlock()
	delete(createFactory.beanMap, id)
}

func RangeBeans(cb func(val interface{})) {
	for _, itm := range createFactory.beanMap {
		cb(itm)
	}
}

func RangeBeans_DoInitialize() {
	RangeBeans(func(val interface{}) {
		if intf, ok := val.(I_initializer); ok {
			intf.DoInitialize()
		}
	})
}
